<!-- Licensed under a BSD license. See license.html for license -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>WebGL2 - Specular Lighting Diagram</title>
<link type="text/css" href="../../resources/webgl-tutorials.css" rel="stylesheet" />
<style>
@media (prefers-color-scheme: dark) {
  canvas {
    background: #444;
  }
}
</style>
</head>
<body>
<div class="description">
</div>
<div style="position:absolute;">
  <canvas id="canvas" width="500" height="300" style="width: 500px; height: 400px;"></canvas>
</div>
<div id="uiContainer">
  <div id="ui">
    <div id="rotation"></div>
  </div>
</div>
</body>
</html>
<!--
for most samples webgl-utils only provides shader compiling/linking and
canvas resizing because why clutter the examples with code that's the same in every sample.
See https://webgl2fundamentals.org/webgl/lessons/webgl-boilerplate.html
and https://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
for webgl-utils, m3, m4, and webgl-lessons-ui.
-->
<script src="../../resources/webgl-lessons-ui.js"></script>
<script src="../../resources/webgl-utils.js"></script>
<script src="../../resources/lessons-helper.js"></script> <!-- you can and should delete this script. it is only used on the site to help with errors -->
<script src="../../resources/m3.js"></script>
<script src="diagram.js"></script>
<script>
"use strict";

function main() {
  const opt = getQueryParams();
  const lang = {
    surface: opt.surface || "surface",
    normal: opt.normal || "normal",
    dot: opt.dot || "dot(halfVector,surfaceNormal) = ",
    surface2View: opt.surface2View || "surface2view",
    surface2Light: opt.surface2Light || "surface2light",
    halfVector: opt.halfVector || "halfVector",
  };
  var ctx = document.querySelector("#canvas").getContext("2d");
  var surfaceAngle = 0;

  function radToDeg(rad) {
    return rad * 180 / Math.PI;
  }

  function degToRad(deg) {
    return deg * Math.PI / 180;
  }

  webglLessonsUI.setupSlider("#rotation", {value: radToDeg(surfaceAngle), slide: updateSurfaceAngle, min: -40, max: 40 });

  function updateSurfaceAngle(event, ui) {
    surfaceAngle = degToRad(ui.value);
    render();
  }

  const darkColors = {
    arrow: '#DDD',
    surfaceNormal: '#0C0',
    surfaceNormalOutline: '#444',
    halfVector: '#F0F',
  };
  const lightColors = {
    arrow: '#000',
    surfaceNormal: '#080',
    surfaceNormalOutline: '#FFF',
    halfVector: 'purple',
  };

  const darkMatcher = window.matchMedia("(prefers-color-scheme: dark)");
  darkMatcher.addEventListener('change', render);

  function render() {
    const isDarkMode = darkMatcher.matches;
    const colors = isDarkMode ? darkColors : lightColors;
    webglUtils.resizeCanvasToDisplaySize(ctx.canvas, window.devicePixelRatio);
    var width  = 250;
    var height = 200;

    var baseScale = Math.min(ctx.canvas.width / width,  ctx.canvas.height / height);

    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.save();
    ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
    ctx.scale(baseScale, baseScale);

    ctx.font = "5pt sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";

    var ex = -width / 3;
    var ey = -height / 4 + 40;

    var sx = 0;
    var sy = height / 6 + 20;

    // draw ray and reflection
    var lx = width / 3;
    var ly = -height / 4;

    ctx.save();
    ctx.translate(sx, sy);
    ctx.rotate(surfaceAngle);
    // draw normal
    var nx = 0;
    var ny = -20;
    ctx.fillStyle = colors.surfaceNormal;
    ctx.strokeStyle = colors.surfaceNormal;
    diagram.arrow(ctx, 0, 0, nx, ny, false, true);
    ctx.fillText(lang.surface, nx, ny - 22);
    ctx.fillText(lang.normal, nx, ny - 14);


    var en = m3.normalize(ex - sx, ey - sy);
    var ln = m3.normalize(lx - sx, ly - sy);
    var h = m3.normalize(en[0] + ln[0], en[1] + ln[1]);

    // draw surface
    //ctx.fillRect(-width / 4, height / 6, width / 2, 20);
    //return;
    diagram.roundedRect(ctx, -width / 4, 0, width / 2, 20);
    var sn = m3.normalize(ex - sx, ey - sy);
    var d  = m3.dot(Math.sin(surfaceAngle), -Math.cos(surfaceAngle), h[0], h[1]);

    var gradient =  ctx.createRadialGradient(0, 0, 0, 0, 0, width / 2);
    gradient.addColorStop(0, diagram.hsl(0, 1, d * 0.5 + 0.5));
    gradient.addColorStop(1, diagram.hsl(0, 1, 0.5));
    ctx.fillStyle = gradient; //diagram.rgb(1,0,0);
//    ctx.fillStyle = diagram.rgb(1,0,0);
    ctx.fill();
    ctx.strokeStyle = diagram.rgb(0,0,0);
    ctx.stroke();
    ctx.fillStyle = "#000"
    ctx.fillText(lang.dot + d.toFixed(2), 0, 10);

    ctx.restore();

    ctx.fillStyle = "orange";
    diagram.drawSun(ctx, lx, ly, width / 10);

    ctx.fillStyle = colors.arrow;
    ctx.strokeStyle = colors.arrow;
    ctx.save();
    ctx.translate(sx, sy);
    ctx.rotate(-Math.atan2(sx - ex, sy - ey) + Math.PI);

    var ed = m3.distance(ex, ey, sx, sy) * 0.70;
    diagram.arrow(ctx, 0, 0, 0, ed, false, true, 0.5);
    ctx.translate(0, ed / 2);
    ctx.rotate(Math.PI * -0.5);
    ctx.translate(0, 5);
    ctx.fillText(lang.surface2View, 0, 0);
    ctx.restore();


    ctx.save();
    ctx.translate(sx, sy);
    ctx.rotate(-Math.atan2(sx - lx, sy - ly) + Math.PI);

    var sd = m3.distance(lx, ly, sx, sy) * 0.80;
    diagram.arrow(ctx, 0, 0, 0, sd, false, true, 0.5);
    ctx.translate(0, sd / 2);
    ctx.rotate(Math.PI * 0.5);
    ctx.translate(0, 5);
    ctx.fillText(lang.surface2Light, 0, 0);
    ctx.restore();




//    ctx.save();
//    ctx.translate(sx, sy);
//
//
//    var i = normalize(sx - lx, sy - ly);
//    var ix = i[0];
//    var iy = i[1];
//
//    var nx = Math.sin(surfaceAngle);
//    var ny = Math.cos(surfaceAngle);
//
//    var r = reflect(ix, iy, nx, ny);
//    var ra = -Math.atan2(r[1], r[0]);
//    ctx.rotate(ra);
//    var rl = distance(sx, sy, ex, ey) * 0.8;
//    diagram.arrow(ctx, 0, 0, 0, rl, false, true, 0.5);
//    ctx.translate(0, rl / 2);
//    ctx.rotate(Math.PI * -0.5);
//    ctx.translate(0, 7);
//    ctx.fillText("relfection", 0, 0);
//    ctx.restore();

    ctx.save();
    ctx.fillStyle = colors.halfVector;
    ctx.strokeStyle = colors.halfVector;
    ctx.translate(sx, sy);
    ctx.rotate(-Math.atan2(h[0], h[1]));
    diagram.arrow(ctx, 0, 0, 0, 60, false, true, 0.7);
    ctx.rotate(Math.PI);
    ctx.fillText(lang.halfVector, 0, -70);
    ctx.restore();



    // draw eye
    ctx.fillStyle = "brown";
    diagram.drawEye(ctx, ex, ey, width / 8, height / 5);


  //  // draw normals
  //  ctx.fillStyle = "#000";
  //  for (var ii = 0; ii <= 12; ++ii) {
  //    var a = ii / 12 * Math.PI;
  //    var x = Math.cos(a) * 50;
  //    var y = Math.sin(a) * 50;
  //    diagram.arrow(ctx, -x, -y, x, y, true, true, 0.5);
  //  }

    // draw rays



    ctx.restore();
  }
  render();
}

function getQueryParams() {
  var params = {};
  if (window.location.search) {
    window.location.search.substring(1).split("&").forEach(function(pair) {
      var keyValue = pair.split("=").map(function (kv) {
        return decodeURIComponent(kv);
      });
      params[keyValue[0]] = keyValue[1];
    });
  }
  return params;
}

main();
</script>

